#include "components/selectshape/selectshape.h"
#include <QRectF>
#include <QPainterPath>
#include <QPointF>
#include <QPainter>
#include <QDebug>
#include <QPen>
SelectRegion::SelectRegion():
	m_width(8),
	m_scaling(0),
	m_rectHeight(0),
	m_rectWidth(0)
{

}

SelectRegion::SelectRegion(const QRectF& rect)
{

}

SelectRegion::~SelectRegion()
{

}

void SelectRegion::setRect(const QRectF& rect, double scaling /*= 1.0*/)
{
	m_scaling = scaling;
	m_rectWidth = rect.width();
	m_rectHeight = rect.height();
	QRectF tepmRect = QRectF(rect.topLeft().x()*scaling,rect.topLeft().y()*scaling,rect.width()*scaling
		,rect.height()*scaling);
	m_topLeft = tepmRect.topLeft();
	m_topRight = tepmRect.topRight();
	m_bottomLeft = tepmRect.bottomLeft();
	m_bottomRight = tepmRect.bottomRight();
	m_centerP = QPointF((m_topLeft.x() + m_bottomRight.x()) / 2, (m_topLeft.y() + m_bottomRight.y()) / 2);
	m_topMid = QPointF((m_topLeft.x() + m_topRight.x()) / 2, m_topLeft.y());
	m_midLeft = QPointF(m_topLeft.x(), (m_topLeft.y() + m_bottomLeft.y()) / 2);
	m_midRight = QPointF(m_topRight.x(), (m_topRight.y() + m_bottomRight.y()) / 2);
	m_bottomMid = QPointF(m_topMid.x(), m_bottomLeft.y());
	
}

void SelectRegion::setRectWidth(const double w)
{
	m_width = w;
}

void SelectRegion::setRotate(const double& rt)
{
	m_rorate = rt;
}

void SelectRegion::setCenterP(const QPointF& centerP)
{
	m_centerP = centerP;
}

bool SelectRegion::containsClicked(const QPointF& clickedPos)
{
	QPointF clickp = clickedPos;
	if(0!= m_rorate){
		double x = (clickedPos.x() - m_centerP.x()) * cos(-m_rorate / 180 * PI) - (clickedPos.y() - m_centerP.y()) * sin(-m_rorate / 180 * PI) + m_centerP.x();
		double y = (clickedPos.x() - m_centerP.x()) * sin(-m_rorate / 180 * PI) + (clickedPos.y() - m_centerP.y()) * cos(-m_rorate / 180 * PI) + m_centerP.y();
		clickp = QPointF(x, y);
	}
	if (m_topLeft == m_bottomRight && m_topRight == m_bottomLeft) {
		return false;
	}
	QPainterPath path;
	path.addRect(topLeftRect(false));
	if (path.controlPointRect().contains(clickp)) return true;
	path.clear();
	path.addRect(topRightRect(false));
	if (path.controlPointRect().contains(clickp)) return true;
	path.clear();
	path.addRect(bottomLeftRect(false));
	if (path.controlPointRect().contains(clickp)) return true;
	path.clear();
	path.addRect(bottomRightRect(false));
	if (path.controlPointRect().contains(clickp)) return true;
	path.clear();
	path.addRect(topMidRect(false));
	if (path.controlPointRect().contains(clickp)) return true;
	path.clear();
	path.addRect(MidLeftRect(false));
	if (path.controlPointRect().contains(clickp)) return true;
	path.clear();
	path.addRect(MidRightRect(false));
	if (path.controlPointRect().contains(clickp)) return true;
	path.clear();
	path.addRect(bottomMidRect(false));
	if (path.controlPointRect().contains(clickp)) return true;
	path.clear();
	path.addRect(rotateRect(false));
	if (path.controlPointRect().contains(clickp)) return true;

	return false;

}

SelectRegion::SelectPos SelectRegion::graphChangeClicked(const QPointF& clickpos)
{
	QPointF clickp = clickpos;
	if (0 != m_rorate) {
		double x = (clickpos.x() - m_centerP.x()) * cos(-m_rorate / 180 * PI) - (clickpos.y() - m_centerP.y()) * sin(-m_rorate / 180 * PI) + m_centerP.x();
		double y = (clickpos.x() - m_centerP.x()) * sin(-m_rorate / 180 * PI) + (clickpos.y() - m_centerP.y()) * cos(-m_rorate / 180 * PI) + m_centerP.y();
		clickp = QPointF(x, y);
	}
	QPainterPath path;
	path.addRect(topLeftRect(false));
	if (path.controlPointRect().contains(clickp)) return SelectPos::TopLeft;
	path.clear();
	path.addRect(topRightRect(false));
	if (path.controlPointRect().contains(clickp)) return SelectPos::TopRight;
	path.clear();
	path.addRect(bottomLeftRect(false));
	if (path.controlPointRect().contains(clickp)) return SelectPos::BottomLeft;
	path.clear();
	path.addRect(bottomRightRect(false));
	if (path.controlPointRect().contains(clickp)) return  SelectPos::BottomRight;
	path.clear();
	path.addRect(topMidRect(false));
	if (path.controlPointRect().contains(clickp)) return  SelectPos::TopMid;
	path.clear();
	path.addRect(MidLeftRect(false));
	if (path.controlPointRect().contains(clickp)) return  SelectPos::MidLeft;
	path.clear();
	path.addRect(MidRightRect(false));
	if (path.controlPointRect().contains(clickp)) return  SelectPos::MidRight;
	path.clear();
	path.addRect(bottomMidRect(false));
	if (path.controlPointRect().contains(clickp)) return  SelectPos::BottomMid;
	path.clear();
	path.addRect(rotateRect(false));
	if (path.controlPointRect().contains(clickp)) return  SelectPos::RotatePos;

	return SelectPos::UselessPos;

}



void SelectRegion::changeGraph(Shape::SvgAbstractShape* graph, SelectPos& selected, const QPointF& lastp, const QPointF& endp)
{

	QPointF mlastp = lastp;
	QPointF mendp = endp;
	if (0 != m_rorate)
	{
		double x = (lastp.x() - m_centerP.x()) * cos(-m_rorate / 180 * PI) - (lastp.y() - m_centerP.y()) * sin(-m_rorate / 180 * PI) + m_centerP.x();
		double y = (lastp.x() - m_centerP.x()) * sin(-m_rorate / 180 * PI) + (lastp.y() - m_centerP.y()) * cos(-m_rorate / 180 * PI) + m_centerP.y();
		mlastp = QPointF(x, y);
		x = (endp.x() - m_centerP.x()) * cos(-m_rorate / 180 * PI) - (endp.y() - m_centerP.y()) * sin(-m_rorate / 180 * PI) + m_centerP.x();
		y = (endp.x() - m_centerP.x()) * sin(-m_rorate / 180 * PI) + (endp.y() - m_centerP.y()) * cos(-m_rorate / 180 * PI) + m_centerP.y();
		mendp = QPointF(x, y);
	}
	double sx = mendp.x() - mlastp.x();
	double sy = mendp.y() - mlastp.y();
	switch (selected)
	{
	case SelectPos::TopLeft:
	{
		if (0 != m_rorate)
			graph->zoomShape(-sx, -sy, graph->getCenterPointF());
		else
			graph->zoomShape(-sx, -sy, graph->getRectF().bottomRight());
	}
	break;
	case SelectPos::TopRight:
	{
		if (0 != m_rorate)
			graph->zoomShape(sx, -sy, graph->getCenterPointF());
		else
			graph->zoomShape(sx, -sy, graph->getRectF().bottomLeft());
	}
	break;
	case SelectPos::BottomLeft:
	{
		if (0 != m_rorate)
			graph->zoomShape(-sx, sy, graph->getCenterPointF());
		else
			graph->zoomShape(-sx, sy, graph->getRectF().topRight());
	}
	break;
	case SelectPos::BottomRight:
	{
		if (0 != m_rorate)
			graph->zoomShape(sx, sy, graph->getCenterPointF());
		else
			graph->zoomShape(sx, sy, graph->getRectF().topLeft());
	}
	break;
	case SelectPos::TopMid:
	{
		if (0 != m_rorate)
			graph->zoomShape(0, -sy, graph->getCenterPointF());
		else
			graph->zoomShape(0, -sy, graph->getRectF().bottomLeft());
	}
	break;
	case SelectPos::MidLeft:
	{
		if (0 != m_rorate)
			graph->zoomShape(-sx, 0, graph->getCenterPointF());
		else
			graph->zoomShape(-sx, 0, graph->getRectF().topRight());
	}
	break;
	case SelectPos::MidRight:
	{
		if (0 != m_rorate)
			graph->zoomShape(sx, 0, graph->getCenterPointF());
		else
			graph->zoomShape(sx, 0, graph->getRectF().topLeft());
	}
	break;
	case SelectPos::BottomMid:
	{
		if (0 != m_rorate)
			graph->zoomShape(0, sy, graph->getCenterPointF());
		else
			graph->zoomShape(0, sy, graph->getRectF().topRight());
	}
	break;
	case SelectPos::RotatePos:
	{
		graph->setRatotion(graph->getRatotion() - getAngleInCenter(lastp, endp, graph->getCenterPointF()));
	}
	break;
	default:
		break;
	}
}

void SelectRegion::paintSurroundRect(QPainter* painter)
{
	QPen pen;
	pen.setColor(QColor("#8A2BE2"));
	pen.setWidth(1);
	painter->setPen(pen);
	pen.setStyle(Qt::DotLine);
	if (0 != m_rorate) {
		painter->translate(m_centerP);
		QPointF startp = m_topLeft - m_centerP;
		QPointF endp = m_bottomRight - m_centerP;
		painter->rotate(m_rorate);
		painter->drawRect(QRectF(startp,endp));
	}
	else
	{
		painter->drawRect(QRectF(m_topLeft, m_bottomRight));
		painter->drawLine(m_topMid, m_topMid - QPointF(0, 30));
	}
	//painter->restore();
	if (0 != m_rorate)
	{
		painter->translate(m_centerP);
		painter->rotate(m_rorate);
	}
	painter->setBrush(QColor("#0082e4"));
	painter->drawEllipse(rotateRect(true));
	painter->drawRect(topLeftRect(true));
	painter->drawRect(topRightRect(true));
	painter->drawRect(bottomLeftRect(true));
	painter->drawRect(bottomRightRect(true));
	painter->drawRect(topMidRect(true));
	painter->drawRect(MidLeftRect(true));
	painter->drawRect(MidRightRect(true));
	painter->drawRect(bottomMidRect(true));
	//painter->drawRect(ParameterRect(true));
	painter->save();
	QPen pen1;
	pen.setWidth(1);
	pen.setColor(QColor("#FF5454"));
	QBrush brush;
	brush.setColor(QColor("#FF5454"));
	brush.setStyle(Qt::SolidPattern);
	painter->setPen(pen1);
	painter->setBrush(brush);
	painter->drawRoundedRect(ParameterRect(true),5,5);
	painter->save();
	QPen pen2;
	pen2.setWidth(1);
	pen2.setColor(QColor("#ffffff"));
	painter->setPen(pen2);
	painter->setBrush(Qt::NoBrush);
	QFont font = painter->font();
	font.setPixelSize(12);
	painter->setFont(font);
	painter->drawText(ParameterRect(true), Qt::AlignHCenter | Qt::AlignVCenter, QString::number(m_rectWidth) + "x" + QString::number(m_rectHeight));
	painter->restore();
	painter->restore();
	
}

QRectF SelectRegion::rotateRect(bool judge /*= true*/) const
{
	if (0 != m_rorate && judge) 
	{
		return QRectF(QPointF(m_topMid.x() - m_centerP.x() - m_width / 2, m_topMid.y()- m_centerP.y() - m_width / 2 - 30),
			QPointF(m_topMid.x()-m_centerP.x()+m_width/2,m_topMid.y()-m_centerP.y()+m_width/2-30));

	}
	else
	{
		return QRectF(QPointF(m_topMid.x() - m_width / 2, m_topMid.y() - m_width / 2 - 30),
			QPointF(m_topMid.x() + m_width / 2, m_topMid.y() + m_width / 2 - 30)
			);
	}
}

QRectF SelectRegion::topLeftRect(bool judge /*= true*/) const
{
	if (0 != m_rorate && judge)
	{
		return QRectF(QPointF(m_topLeft.x() - m_centerP.x() - m_width / 2, m_topLeft.y() - m_centerP.y() - m_width / 2),
			QPointF(m_topLeft.x() - m_centerP.x() + m_width / 2, m_topLeft.y() - m_centerP.y() + m_width / 2));
	}
	else
		return QRectF(QPointF(m_topLeft.x() - m_width / 2, m_topLeft.y() - m_width / 2),
			QPointF(m_topLeft.x() + m_width / 2, m_topLeft.y() + m_width / 2));
}

QRectF SelectRegion::topRightRect(bool judge /*= true*/) const
{
	if (0 != m_rorate && judge)
	{
		return QRectF(QPointF(m_topRight.x() - m_centerP.x() - m_width / 2, m_topRight.y() - m_centerP.y() - m_width / 2),
			QPointF(m_topRight.x() - m_centerP.x() + m_width / 2, m_topRight.y() - m_centerP.y() + m_width / 2));
	}
	else
		return QRectF(QPointF(m_topRight.x() - m_width / 2, m_topRight.y() - m_width / 2),
			QPointF(m_topRight.x() + m_width / 2, m_topRight.y() + m_width / 2));
}

QRectF SelectRegion::bottomLeftRect(bool judge /*= true*/) const
{
	if (0 != m_rorate && judge)
	{
		return QRectF(QPointF(m_bottomLeft.x() - m_centerP.x() - m_width / 2, m_bottomLeft.y() - m_centerP.y() - m_width / 2),
			QPointF(m_bottomLeft.x() - m_centerP.x() + m_width / 2, m_bottomLeft.y() - m_centerP.y() + m_width / 2));
	}
	else
		return QRectF(QPointF(m_bottomLeft.x() - m_width / 2, m_bottomLeft.y() - m_width / 2),
			QPointF(m_bottomLeft.x() + m_width / 2, m_bottomLeft.y() + m_width / 2));
}

QRectF SelectRegion::bottomRightRect(bool judge /*= true*/) const
{
	if (0 != m_rorate && judge)
	{
		return QRectF(QPointF(m_bottomRight.x() - m_centerP.x() - m_width / 2, m_bottomRight.y() - m_centerP.y() - m_width / 2),
			QPointF(m_bottomRight.x() - m_centerP.x() + m_width / 2, m_bottomRight.y() - m_centerP.y() + m_width / 2));
	}
	else
		return QRectF(QPointF(m_bottomRight.x() - m_width / 2, m_bottomRight.y() - m_width / 2),
			QPointF(m_bottomRight.x() + m_width / 2, m_bottomRight.y() + m_width / 2));
}

QRectF SelectRegion::topMidRect(bool judge /*= true*/) const
{
	if (0 != m_rorate && judge)
	{
		return QRectF(QPointF(m_topMid.x() - m_centerP.x() - m_width / 2, m_topMid.y() - m_centerP.y() - m_width / 2),
			QPointF(m_topMid.x() - m_centerP.x() + m_width / 2, m_topMid.y() - m_centerP.y() + m_width / 2));
	}
	else
		return QRectF(QPointF(m_topMid.x() - m_width / 2, m_topMid.y() - m_width / 2),
			QPointF(m_topMid.x() + m_width / 2, m_topMid.y() + m_width / 2));
}

QRectF SelectRegion::MidLeftRect(bool judge /*= true*/) const
{
	if (0 != m_rorate && judge)
	{
		return QRectF(QPointF(m_midLeft.x() - m_centerP.x() - m_width / 2, m_midLeft.y() - m_centerP.y() - m_width / 2),
			QPointF(m_midLeft.x() - m_centerP.x() + m_width / 2, m_midLeft.y() - m_centerP.y() + m_width / 2));
	}
	else
		return QRectF(QPointF(m_midLeft.x() - m_width / 2, m_midLeft.y() - m_width / 2),
			QPointF(m_midLeft.x() + m_width / 2, m_midLeft.y() + m_width / 2));
}

QRectF SelectRegion::MidRightRect(bool judge /*= true*/) const
{
	if (0 != m_rorate && judge)
	{
		return QRectF(QPointF(m_midRight.x() - m_centerP.x() - m_width / 2, m_midRight.y() - m_centerP.y() - m_width / 2),
			QPointF(m_midRight.x() - m_centerP.x() + m_width / 2, m_midRight.y() - m_centerP.y() + m_width / 2));
	}
	else
		return QRectF(QPointF(m_midRight.x() - m_width / 2, m_midRight.y() - m_width / 2),
			QPointF(m_midRight.x() + m_width / 2, m_midRight.y() + m_width / 2));
}

QRectF SelectRegion::bottomMidRect(bool judge /*= true*/) const
{
	if (0 != m_rorate && judge)
	{
		return QRectF(QPointF(m_bottomMid.x() - m_centerP.x() - m_width / 2, m_bottomMid.y() - m_centerP.y() - m_width / 2),
			QPointF(m_bottomMid.x() - m_centerP.x() + m_width / 2, m_bottomMid.y() - m_centerP.y() + m_width / 2));
	}
	else
		return QRectF(QPointF(m_bottomMid.x() - m_width / 2, m_bottomMid.y() - m_width / 2),
			QPointF(m_bottomMid.x() + m_width / 2, m_bottomMid.y() + m_width / 2));
}

QRectF SelectRegion::ParameterRect(bool judge /*= true*/) const
{
	if (0 != m_rorate && judge) {
		//return QRectF(QPointF(m_bottomMid.x()-m_centerP.x()-));
	}
	else
	{
		return QRectF(QPointF(m_bottomMid.x()-30,m_bottomMid.y()+5),QPointF(m_bottomMid.x()+30,m_bottomMid.y()+25));
	}
}

double SelectRegion::getAngleInCenter(const QPointF& startp, const QPointF& endp, const QPointF& centerp)
{
	double angle = atan2(endp.x() - centerp.x(), endp.y() - centerp.y())
		- atan2(startp.x() - centerp.x(), startp.y() - centerp.y());
	if (angle > PI)
		angle -= 2 * PI;
	else if (angle < -2 * PI)
		angle += 2 * PI;
	angle = angle * 180 / PI;
	return angle;
}

SelectRect::SelectRect()
{

}

SelectRect::~SelectRect()
{

}

void SelectRect::setPath(const QVector<QPointF>& path)
{
	m_path = path;
}

void SelectRect::setShapeInSelect(QVector<Shape::SvgAbstractShape*>& shapes)
{
	m_shapeSelected = shapes;
	double minX = m_shapeSelected[0]->getRectF().x(),
		minY = m_shapeSelected[0]->getRectF().y(),
		maxX = m_shapeSelected[0]->getRectF().x(),
		maxY = m_shapeSelected[0]->getRectF().y();
	for (auto it : m_shapeSelected) {
		minX = it->getRectF().x() < minX ? it->getRectF().x() : minY;
		minY = it->getRectF().y() < minY ? it->getRectF().y() : minY;
	}
	m_topLeft = QPointF(minX,minY);
}

bool SelectRect::shapeInSelectRect(Shape::SvgAbstractShape* shape)
{
	if (2 != m_path.size())
		return false;
	QRectF rect = shape->getRectF();
	QPainterPath path;
	path.addRect(QRectF(m_path[0], m_path[1]).normalized());
	if (path.controlPointRect().contains(rect.topLeft()))
		return true;
	if (path.controlPointRect().contains(rect.topRight()))
		return true;
	if (path.controlPointRect().contains(rect.bottomLeft()))
		return true;
	if (path.controlPointRect().contains(rect.bottomRight()))
		return true;
	if (path.controlPointRect().contains(rect.center()))
		return true;
	return false;
}

void SelectRect::selectedShapes(QVector<Shape::SvgAbstractShape*>& shapes)
{
	m_shapeSelected.clear();
	int size = shapes.size();
	for (int i = 0; i < size; ++i)
		if (shapeInSelectRect(shapes[i]))
			m_shapeSelected.push_back(shapes[i]);
}

void SelectRect::moveSelectedShaps(const double& x, const double& y)
{
	int size = m_shapeSelected.size();
	for (int i = 0; i < size; ++i)
		m_shapeSelected[i]->moveTo(x, y);
}

void SelectRect::setSelectedShapsLineColor(const QColor& color)
{
	int size = m_shapeSelected.size();
	for (int i = 0; i < size; ++i)
		m_shapeSelected[i]->setBorderColor(color);

}

void SelectRect::setSelectedGraphsFillColor(const QColor& color)
{

	int size = m_shapeSelected.size();
	for (int i = 0; i < size; ++i)
		m_shapeSelected[i]->setBackgroundColor(color);
}

void SelectRect::setSelectedGraphsLineType(const Qt::PenStyle& type)
{
	int size = m_shapeSelected.size();
	for (int i = 0; i < size; ++i)
		m_shapeSelected[i]->setPenStyle(type);
}

QVector<Shape::SvgAbstractShape*> SelectRect::copySelectedGraphs()
{
	QVector<Shape::SvgAbstractShape*> copyGraphs;
	int size = m_shapeSelected.size();
	for (int i = 0; i < size; ++i)
		//copyGraphs.push_back(m_shapeSelected[i]->copyMyGraph());
	return copyGraphs;
}

void SelectRect::clear()
{
	m_shapeSelected.clear();

}

QPointF SelectRect::getTopLeft() const
{
	return m_topLeft;
}

int SelectRect::getGraphsNums() const
{
	return m_shapeSelected.size();
}

QVector<Shape::SvgAbstractShape*> SelectRect::getSelectedGraphs() const
{
	return m_shapeSelected;
}

bool SelectRect::containsPointF(const QPointF& pointF) const
{
	int size = m_shapeSelected.size();
	for (int i = 0; i < size; ++i)
		if (m_shapeSelected[i]->isContains(pointF))
			return true;
	return false;
}

void SelectRect::paintRect(QPainter& painter, QPen& pen, bool visible /*= false*/, const double& scaling /*= 1.0*/)
{
	if (!visible)
		return;
	pen.setColor(QColor("#0082e4"));
	pen.setWidth(1);
	pen.setStyle(Qt::DotLine);
	painter.setPen(pen);
	QPointF newStartPos = QPointF(m_path[0] * scaling);
	QPointF newEndPos = QPointF(m_path[1] * scaling);
	//painter.drawRect(QRectF(newStartPos, newEndPos));
	painter.fillRect(QRectF(newStartPos,newEndPos),QBrush(QColor(128, 128, 255, 128)));
}

void SelectRect::paintSelectedGraphRect(QPainter& painter, QPen& pen, bool visible /*= false*/, const double& scaling /*= 1.0*/)
{
	if (!visible)
		return;
	pen.setColor(QColor("#0082e4"));
	pen.setWidth(1);
	pen.setStyle(Qt::DotLine);
	painter.setPen(pen);
	int size = m_shapeSelected.size();
	QRectF rect;
	for (int i = 0; i < size; ++i)
	{
		painter.save();
		rect = m_shapeSelected[i]->getRectF();
		if (0 != m_shapeSelected[i]->getRatotion())
		{
			painter.translate(m_shapeSelected[i]->getCenterPointF() * scaling);
			painter.rotate(m_shapeSelected[i]->getRatotion());
			rect = QRectF((rect.topLeft().x() - m_shapeSelected[i]->getCenterPointF().x()) * scaling,
				(rect.topLeft().y() - m_shapeSelected[i]->getCenterPointF().y()) * scaling
				, rect.width() * scaling, rect.height() * scaling);
		}
		else
			rect = QRectF(rect.topLeft().x() * scaling, rect.topLeft().y() * scaling
				, rect.width() * scaling, rect.height() * scaling);

		painter.drawRect(rect);
		//painter.fillRect(rect, QBrush(QColor(128, 128, 255, 128)));
		
		painter.restore();
	}
}

Grid::Grid():m_w(0),m_h	(0)
{

}

Grid::~Grid()
{

}

void Grid::setSize(const int& w, const int& h)
{
	m_w = w;
	m_h = h;
}

void Grid::paintGrid(QPainter& painter, const double& m_salcing /*= 1.0*/)
{
	painter.save();
	QPen pen(QColor("#8C8C8C"));
	pen.setStyle(Qt::SolidLine);
	pen.setWidthF(1);
	painter.setPen(pen);
	for (int x = 0; x < m_w; x += 25)
	{
		painter.drawLine(QPoint(x, 1), QPoint(x, m_h));
	}
	for (int y = 0; y < m_h; y += 25)
	{
		painter.drawLine(QPoint(1, y), QPoint(m_w, y));
	}
	painter.restore();
}
